package utils

import (
	"encoding/json"
	"fmt"
	"sync"
)

type SyncData struct {
	Data         map[int]int   `json:"data"`
	Miu          float64       `json:"miu"`
	Sigma        float64       `json:"sigma"`
	RwMutex      *sync.RWMutex `json:"rwMutex"`
	Que          *Queue        `json:"que"`
	Offset       int64         `json:"offset"`
	RecordOffset int64         `json:"RecordOffset"`
	Min          int           `json:"min"`
	Max          int           `json:"max"`
}

func NewSyncMap(max int, min int, size int) *SyncData {
	obj := new(SyncData)
	obj.Data = make(map[int]int)
	obj.RwMutex = new(sync.RWMutex)
	obj.Que = GetQueue(size)
	obj.Max = min
	obj.Min = max

	for i := min; i <= max; i++ {
		obj.Data[i] = 0
	}

	return obj
}

func (obj *SyncData) Append(nums int, offset int64) {
	obj.RwMutex.Lock()
	out, data := obj.Que.InQueue(nums)

	if out {
		obj.Data[data]--
	}

	obj.Data[nums]++
	obj.Offset = obj.RecordOffset
	defer obj.RwMutex.Unlock()
}

//建议 队列长度*100(ms/个)*0.1 时间调用一次，即队列长度/100等于调用秒次，每更新10%左右的数据刷新一次统计结果

func (obj *SyncData) Count(min int, max int) {
	obj.RwMutex.Lock()
	var miu float64 = 0.0
	len := 0

	for k, v := range obj.Data {
		len += v
		miu += float64(k) * float64(v)
	}

	miu /= float64(len)

	var sigma float64 = 0

	countMax := min
	countMin := max

	for k, v := range obj.Data {
		if v != 0 {

			if countMax < k {
				countMax = k
			}
			if countMin > k {
				countMin = k
			}

			sigma += (float64(k) - miu) * (float64(k) - miu) * float64(v)
		}
	}

	obj.Miu = miu
	obj.Sigma = sigma / float64(len)
	obj.Min = countMin
	obj.Max = countMax
	obj.RecordOffset = obj.Offset
	fmt.Println("均值，方差", miu, sigma/float64(len))
	defer obj.RwMutex.Unlock()
}

func (obj *SyncData) GetDateByByte() []byte {
	obj.RwMutex.RLock()
	defer obj.RwMutex.RUnlock()

	//var data map[string]interface{}
	//data = map[string]interface{}{}
	//data["min"] = obj.Min
	//data["max"] = obj.Max
	//data["miu"] = obj.Miu
	//data["sigma"] = obj.Sigma
	//data["offset"] = obj.RecordOffset
	//buffer, _ := json.Marshal(&data)

	buffer, _ := json.Marshal(obj)
	fmt.Println("obj", string(buffer))
	return buffer
}
